home *** CD-ROM | disk | FTP | other *** search
/ Aminet 48 / Aminet 48 (2002)(GTI - Schatztruhe)[!][Apr 2002].iso / Aminet / util / conv / Wav2Cas.lha / Original stuff / WAV2CAS.C next >
Encoding:
C/C++ Source or Header  |  2002-02-18  |  59.1 KB  |  1,664 lines

  1. /*****************************************************************************
  2. **
  3. **  Copyright 1996, 1997 by Ernest R. Schreurs.
  4. **  All rights reserved.
  5. **  Use of this source code is allowed under the following conditions:
  6. **  You must inform people that you based your work on this stuff.
  7. **  If you charge a fee in any form for your product, you must inform people
  8. **  that this stuff is available free of charge.
  9. **  Refer to the documentation for more information.
  10. **
  11. *****************************************************************************/
  12. #define MODULE  "WAV2CAS.C"
  13. /*****************************************************************************
  14. **  NAME: WAV2CAS.C
  15. **
  16. **  Author            : Ernest R. Schreurs
  17. **  Date              : May 1, 1997
  18. **  Release           : 01.00
  19. **
  20. **  Description       : This program will convert a .wav sound file to
  21. **                      a format known as the .cas format.  It is assumed
  22. **                      that the wav file contains a sample of a Classic Atari
  23. **                      cassette tape.  This program converts the FSK sounds to
  24. **                      the data they are representing.
  25. **
  26. *****************************************************************************/
  27.  
  28. /*****************************************************************************
  29. ==  INCLUDE FILES
  30. *****************************************************************************/
  31. #include <stdio.h>              /* For printf() and gets()              */
  32. #include <ctype.h>              /* For isalnum() and toupper()          */
  33. #include <stdlib.h>             /* For the exit function                */
  34. #include <string.h>             /* String and memory stuff              */
  35.  
  36. /*****************************************************************************
  37. ==  DEFINED SYMBOLS
  38. *****************************************************************************/
  39.  
  40. #ifndef FALSE
  41. #define FALSE               0
  42. #endif
  43. #ifndef TRUE
  44. #define TRUE                1
  45. #endif
  46.  
  47. #ifndef NULL
  48. #define NULL                0
  49. #endif
  50. #define PATH_LEN            128             /* Maximum path length          */
  51.  
  52. #define BUF_LEN             80              /* fgets buffer length          */
  53. #define SUCCESS             1               /* Success is non-zero          */
  54. #define FAILURE             0               /* Failure is zero              */
  55.  
  56. /*
  57. **  The PCM data is read from the wave file into a PCM buffer.
  58. **  The size of the buffer that is allocated is equal to the value defined
  59. **  below.  It must be an even value.  The buffer is replenished when half
  60. **  of the buffer is empty.  Therefore we also need to know what half of
  61. **  the buffer size is.  Make sure these values agree, if changing one,
  62. **  always change the other too.
  63. */
  64. #define PCM_BUF_LEN         512             /* Size of PCM data buffer      */
  65. #define PCM_BUF_HALF        256             /* Exactly half of above value  */
  66. #define SAMPLE_CNT_TBL_LEN  3000L           /* Size of sample count table   */
  67.  
  68. /*
  69. **  A tape record starts with a Pre-Record Write Tone.
  70. **  Then we find bytes, usually 132, each starting with a startbit,
  71. **  eight data bits, lsb first, followed by a stopbit.
  72. **  This is all coded in mark and space tones, as defined below.
  73. */
  74. #define FSK_MARK            1               /* Mark tone represents a 1     */
  75. #define FSK_SPACE           0               /* Space tone represents a 0    */
  76. #define FSK_1               1               /* A 1 bit is a mark            */
  77. #define FSK_0               0               /* A 0 bit is a space           */
  78. #define FSK_PRWT            1               /* PRWT tone is a mark          */
  79. #define FSK_STARTBIT        0               /* Startbit is a space          */
  80. #define FSK_STOPBIT         1               /* Stopbit is a mark            */
  81.  
  82. /*
  83. **  Definitions for the mark and space tone frequencies.
  84. */
  85. #define FSK_TONE_MARK       5327            /* Frequency of mark tone       */
  86. #define FSK_TONE_SPACE      3995            /* Frequency of space tone      */
  87.  
  88. /*****************************************************************************
  89. ==  MACRO DEFINITIONS
  90. *****************************************************************************/
  91. /*
  92. **  Macro for casting stuff to requirements of stupid
  93. **  standard library functions.
  94. */
  95.  
  96. #define FGETS( buf, buf_len, file_ptr )                                 \
  97.     (void *)fgets( (char *)buf, (int)buf_len, (FILE *)file_ptr )
  98.  
  99. #define STRLEN( str )                                                   \
  100.     strlen( (const char *)(str) )
  101.  
  102. /*
  103. **  Macro for getting input from the terminal,
  104. **  allowing the user to exit with either control Z or
  105. **  inputting the string ^Z to indicate intention of
  106. **  terminating the program.
  107. */
  108. #define GET_BUF()                                                           \
  109. {                                                                           \
  110.     if ( FGETS( buf, BUF_LEN, stdin )  ==  NULL )                           \
  111.     {                                                                       \
  112.         printf( "Terminated by ^Z\n" );                                     \
  113.         exit(0);                                                            \
  114.     }                                                                       \
  115.     if ( memcmp( buf, "^Z", 2 ) == 0 || memcmp( buf, "^z", 2 ) == 0  )      \
  116.     {                                                                       \
  117.         printf( "Terminated by ^Z\n" );                                     \
  118.         exit(0);                                                            \
  119.     }                                                                       \
  120. }
  121.  
  122. #define PRINT( lst )                                                        \
  123. {                                                                           \
  124.     if( diagnostics )                                                       \
  125.     {                                                                       \
  126.         printf lst;                                                         \
  127.     }                                                                       \
  128. }
  129.  
  130. /*****************************************************************************
  131. ==  TYPE and STRUCTURE DEFINITIONS
  132. *****************************************************************************/
  133. typedef     unsigned char   bool;   /* Boolean value                        */
  134. typedef     unsigned char   ubyte;  /* Exactly eight bits, unsigned         */
  135. typedef     short           int16;  /* At least 16 bits, signed             */
  136. typedef     unsigned short  uint16; /* At least 16 bits, unsigned           */
  137. typedef     long            int32;  /* At least 32 bits, signed             */
  138. typedef     unsigned long   uint32; /* At least 32 bits, unsigned           */
  139.  
  140. /*
  141. **  Cassette file header.
  142. */
  143.  
  144. typedef struct
  145. {
  146.     ubyte       cas_record_id[4];       /* Cassette record type             */
  147.     ubyte       cas_len_lo;             /* Record length low byte           */
  148.     ubyte       cas_len_hi;             /* Record length high byte          */
  149.     ubyte       cas_aux1;               /* Type dependant data              */
  150.     ubyte       cas_aux2;               /* Type dependant data              */
  151.     ubyte       cas_data[8192];         /* Data                             */
  152. } cas_blk;
  153.  
  154. /*
  155. **  fsk_cnt stream.  The duration of each mark and space is counted in
  156. **  pairs, since they alternate.
  157. */
  158.  
  159. typedef struct
  160. {
  161.     uint32      sample_pos;             /* Position of sample in .wav file  */
  162.     uint32      sample_cnt_mark;        /* Number of samples in mark state  */
  163.     uint32      sample_cnt_space;       /* Number of samples in space state */
  164. } sample_cnt_blk;
  165.  
  166. /*****************************************************************************
  167. ==  IMPORTED VARIABLES
  168. *****************************************************************************/
  169. /*****************************************************************************
  170. ==  LOCAL ( HIDDEN ) VARIABLES
  171. *****************************************************************************/
  172. static FILE *   wav_file;               /* Wave file                        */
  173. static FILE *   fsk_file;               /* FSK intermediate file            */
  174. static FILE *   hex_file;               /* HEX intermediate file            */
  175. static FILE *   cas_file;               /* Cassette image file              */
  176.  
  177. static cas_blk  cas_rec;                /* The cassette record buffer       */
  178.  
  179. static uint32   cnt_cur;                /* Current period count, rounded    */
  180. static uint32   cnt_next;               /* Next period count                */
  181. static uint32   cnt_prev;               /* Previous period count            */
  182. static uint32   cnt_total;              /* Total sample count               */
  183. static uint32   cnt_val;                /* Current period actual count      */
  184.  
  185. static bool     diagnostics;            /* Print diagnostic data            */
  186. static bool     fsk;                    /* Write FSK table file             */
  187. static bool     fsk_print_first;        /* Writing FSK first line           */
  188. static uint32   sample_cnt_high;        /* High count limit for mark tone   */
  189. static uint32   sample_cnt_irg;         /* Count limit for IRG detection    */
  190. static uint32   sample_cnt_low;         /* Low count limit for mark tone    */
  191. static uint32   sample_cnt_bit;         /* Expected sample count for one bit*/
  192. static uint32   sample_cnt_bit_limit;   /* Low limit count for one bit      */
  193. static uint32   sample_cnt_minimum;     /* Minimum count for complete period*/
  194. static sample_cnt_blk * sample_cnt_tbl; /* Count table                      */
  195. static uint32   sample_tbl_ndx;         /* Count table index                */
  196. static uint16   sample_tbl_level;       /* Current level being counted      */
  197.  
  198. static ubyte    pcm[PCM_BUF_LEN];       /* Buffer with samples              */
  199. static uint32   pcm_bytes;              /* Number of bytes read into buffer */
  200. static uint32   pcm_cnt;                /* Buffer byte count                */
  201. static uint32   pcm_ck_len;             /* Length of PCM data chunk in file */
  202. static uint32   pcm_level_previous;     /* Previous sample level            */
  203. static bool     pcm_level_rising;       /* Rising / falling                 */
  204. static uint32   pcm_ndx;                /* Buffer index pointer             */
  205. static uint32   pcm_ndx_end;            /* Buffer end pointer to free space */
  206.  
  207. static uint32   printed_bytes;          /* Number of bytes printed on line  */
  208. static uint32   sample_rate;            /* Sampling rate                    */
  209.  
  210. /*****************************************************************************
  211. ==  EXPORTED VARIABLES
  212. *****************************************************************************/
  213. /*****************************************************************************
  214. ==  IMPORTED FUNCTIONS
  215. *****************************************************************************/
  216. /*****************************************************************************
  217. ==  LOCAL ( HIDDEN ) FUNCTIONS
  218. *****************************************************************************/
  219. static void     cleanup( void );
  220. static uint32   period_sample_cnt( void );
  221. static void     process_cnt( uint32 cnt, uint16 level );
  222. static uint32   process_header( void );
  223. static void     process_record( void );
  224. static void     replenish_buffer( void );
  225. static void     usage( char * cmd );
  226. static uint32   wav2fsk( void );
  227.  
  228. /*****************************************************************************
  229. ==  EXPORTED FUNCTIONS
  230. *****************************************************************************/
  231. int                 main();                 /* Normal entry point to it all */
  232.  
  233. /*****************************************************************************
  234. ==  LOCAL ( HIDDEN ) FUNCTIONS
  235. *****************************************************************************/
  236.  
  237. /*****************************************************************************
  238. **  NAME:  cleanup()
  239. **
  240. **  PURPOSE:
  241. **      Cleanup any mess that was created.
  242. **
  243. **  DESCRIPTION:
  244. **      This function will attempt to close all open files and
  245. **      free allocated memory.
  246. **
  247. **  INPUT:
  248. **      - The file pointers and paths are used.
  249. **
  250. **  OUTPUT:
  251. **      The function returns nothing.
  252. **
  253. */
  254.  
  255. static void         cleanup( void )
  256. {
  257.     if( wav_file )
  258.     {
  259.         fclose( wav_file );
  260.     }
  261.     if( fsk_file )
  262.     {
  263.         fclose( fsk_file );
  264.     }
  265.     if( hex_file )
  266.     {
  267.         fclose( hex_file );
  268.     }
  269.     if( cas_file )
  270.     {
  271.         fclose( cas_file );
  272.     }
  273.  
  274.     if( sample_cnt_tbl )
  275.         free( (void *)sample_cnt_tbl );
  276.     return;
  277. }
  278.  
  279. /*****************************************************************************
  280. **  NAME:  period_sample_cnt()
  281. **
  282. **  PURPOSE:
  283. **      Count the number of samples within one period.
  284. **
  285. **  DESCRIPTION:
  286. **      This function will count the samples between two period tops.
  287. **
  288. **  INPUT:
  289. **      Nothing.
  290. **      Data is taken from the pcm buffer.
  291. **
  292. **  OUTPUT:
  293. **      Sets the sample count to the number of samples within one period.
  294. **      If this is zero, there are no more samples.
  295. **      Prints results.
  296. **      Returns SUCCESS if data converted successfully.
  297. **      Returns FAILURE if some error occurred.
  298. **
  299. */
  300.  
  301. static uint32       period_sample_cnt( void )
  302. {
  303.  
  304. /*
  305. **  What was the current sample count, will now be the previous value.
  306. **  What was the next sample count, will now be the current value, which
  307. **  will later be rounded by comparing it with the new previous and next
  308. **  sample counts.
  309. **  What was the actual next sample count will be recorded as the value of
  310. **  the sample counter for purposes of timing.
  311. **  Determine the count for the next sample count.
  312. */
  313.     cnt_prev = cnt_val;
  314.     cnt_cur = cnt_next;
  315.     cnt_val = cnt_next;
  316.     cnt_next = 0;
  317.  
  318.     while( pcm_bytes )
  319.     {
  320.  
  321. /*
  322. **  Replenish buffer if beyond the critical mark.
  323. */
  324.         if( pcm_ndx >= PCM_BUF_HALF )
  325.             replenish_buffer();
  326.  
  327. /*
  328. **  For better difference between mark and space, we count one complete
  329. **  period, starting at one top, until the top one period away.
  330. **  We start out with a falling level, back to rising, and when the level
  331. **  stops rising, we have counted one complete period.  In order to eliminate
  332. **  noise, the number of samples must be beyond a treshold.  This by itself
  333. **  does not eliminate noise, but it eliminates low period counts.
  334. */
  335.         if( pcm_level_rising )
  336.         {                                               /* Level rising   */
  337.             if( pcm[pcm_ndx] <= pcm_level_previous )    /* At the top?    */
  338.             {
  339.                 pcm_level_rising = FALSE;
  340.                 pcm_level_previous = 255;
  341.                 if( cnt_next > sample_cnt_minimum )     /* Is it a period?*/
  342.                     break;
  343.             }
  344.             else
  345.                 pcm_level_previous = pcm[pcm_ndx];
  346.         } /* end if level rising */
  347.         else
  348.         {                                               /* Level falling  */
  349.             if( pcm[pcm_ndx] >= pcm_level_previous )    /* At the bottom? */
  350.             {
  351.                 pcm_level_rising = TRUE;
  352.                 pcm_level_previous = 0;
  353.             }
  354.             else
  355.                 pcm_level_previous = pcm[pcm_ndx];
  356.         } /* end else if level rising */
  357.  
  358. /*
  359. **  Count the number of samples within this period.
  360. */
  361.         cnt_next++;
  362.         pcm_ndx++;
  363.         pcm_bytes--;
  364.     }
  365.  
  366. /*
  367. **  Allow for sampling timing differences.  If previous and next value
  368. **  agree, the current sample is made to be the same value.  Otherwise,
  369. **  it remains the sample count value as counted.
  370. */
  371.     if( ( cnt_val == sample_cnt_low ) && ( cnt_next >= sample_cnt_low ) )
  372.         if( cnt_prev > sample_cnt_low )
  373.             cnt_cur = sample_cnt_low + 1;
  374.     if( ( cnt_val == sample_cnt_low ) && ( cnt_next <= sample_cnt_low ) )
  375.         if( cnt_prev < sample_cnt_low )
  376.             cnt_cur = sample_cnt_low - 1;
  377.  
  378.     return( SUCCESS );
  379. }
  380.  
  381. /*****************************************************************************
  382. **  NAME:  process_cnt()
  383. **
  384. **  PURPOSE:
  385. **      The sample count is used to build a table of the duration of each
  386. **      mark and space tone.  Since this is fsk data, when one stops, the
  387. **      other starts, so they are counted in pairs.
  388. **
  389. **  DESCRIPTION:
  390. **      The samples are added to the sample count table.  When there is a
  391. **      complete record in the table, we can output it to the .cas file.
  392. **
  393. **  INPUT:
  394. **      - The number of samples to be represented.
  395. **      - The level represented by the samples.
  396. **
  397. **  OUTPUT:
  398. **      Data is added to the table.
  399. **      The function returns nothing.
  400. **
  401. */
  402.  
  403. static void         process_cnt( cnt, level )
  404. uint32  cnt;                        /* Number of samples of this level      */
  405. uint16  level;                      /* Interpreted level of signal          */
  406. {
  407.  
  408. /*
  409. **  If the level is the same as the previous level, we add the count to the
  410. **  running total.  If the level is not the same, we start a new running total.
  411. **  If the new level is a space, start counting in the space counter.  If the
  412. **  level is a mark, we must increment the buffer pointer, and then we can
  413. **  start counting in the mark counter.
  414. */
  415.  
  416.     if( level == sample_tbl_level )
  417.     {
  418.         if( level == FSK_SPACE )
  419.             sample_cnt_tbl[sample_tbl_ndx].sample_cnt_space += cnt;
  420.         else
  421.             sample_cnt_tbl[sample_tbl_ndx].sample_cnt_mark += cnt;
  422.     }
  423.     else
  424.     {
  425.         sample_tbl_level = level;
  426.         if( level == FSK_SPACE )
  427.         {
  428.             sample_cnt_tbl[sample_tbl_ndx].sample_cnt_space = cnt;
  429.  
  430. /*
  431. **  If this mark was long enough to be recognized as an IRG or PRWT,
  432. **  we can start interpreting the count values as bits and bytes.
  433. */
  434.             if( sample_cnt_tbl[sample_tbl_ndx].sample_cnt_mark > sample_cnt_irg )
  435.             {
  436.                 process_record();
  437.             }
  438.         }
  439.         else
  440.         {
  441.             if( sample_tbl_ndx == SAMPLE_CNT_TBL_LEN )  /* Table full? */
  442.                 process_record();
  443.             sample_tbl_ndx++;
  444.             sample_cnt_tbl[sample_tbl_ndx].sample_cnt_mark = cnt;
  445.             sample_cnt_tbl[sample_tbl_ndx].sample_pos = cnt_total;
  446.         }
  447.     }
  448.  
  449.     cnt_total += cnt;
  450.  
  451.     return;
  452. }
  453.  
  454. /*****************************************************************************
  455. **  NAME:  process_header()
  456. **
  457. **  PURPOSE:
  458. **      Process the data from the header of the .wav file and store
  459. **      relevant information.
  460. **
  461. **  DESCRIPTION:
  462. **      This function will read the relevant data about the .wav file
  463. **      and store it.
  464. **
  465. **  INPUT:
  466. **      Nothing.
  467. **      Data is read from the wave file.
  468. **
  469. **  OUTPUT:
  470. **      Prints results.
  471. **      Stores data related to the format and contents of the wave file.
  472. **      Returns SUCCESS if header was processed successfully.
  473. **      Returns FAILURE if some error occurred.
  474. **
  475. */
  476.  
  477. static uint32       process_header( void )
  478. {
  479.     uint16          bits_sample;            /* Sample size                  */
  480.     uint32          bytes;                  /* Number of bytes read         */
  481.     uint16          channels;               /* Number of channels           */
  482.     uint32          ck_len;                 /* Chunk length                 */
  483.     uint32          fi_len;                 /* File length                  */
  484.     uint16          fmt_tag;                /* Format tag                   */
  485.     ubyte           wav_rec[512];           /* Buffer for wave data         */
  486.  
  487. /*
  488. **  Wave files usually look like this
  489. **
  490. **  char[4] = "RIFF", long file size not including these 8 bytes,
  491. **  char[4] = "WAVE",
  492. **  char[4] = "fmt ", long wave format header size not including these 8 bytes,
  493. **  bunch of longs containing info about sample rate and such,
  494. **  char[4] = "data", long wave data size not including these 8 bytes,
  495. **  gobs of PCM data bytes.
  496. **  See below for more details.
  497. */
  498.  
  499. /*
  500. **  .WAV files should begin with RIFF, followed by the size.
  501. */
  502.     bytes = fread( (char *)wav_rec, (int)1, (int)4, wav_file );
  503.     if( ( bytes < 4 ) || memcmp( wav_rec, "RIFF", 4 ) )
  504.     {
  505.         fprintf(stderr, "\nThis is not a valid .wav file, it does not begin with \"RIFF\".\n");
  506.         return( FAILURE );
  507.     }
  508.  
  509. /*
  510. **  Get the next four bytes and convert them to an uint32 value.
  511. */
  512.     bytes = fread( (char *)wav_rec, (int)1, (int)4, wav_file );
  513.     if( bytes < 4 )
  514.     {
  515.         fprintf(stderr, "\nThis is not a valid .wav file, invalid file length.\n");
  516.         return( FAILURE );
  517.     }
  518.     fi_len = (((((((uint32)wav_rec[3]) << 8 ) + wav_rec[2] ) << 8 )
  519.               + wav_rec[1]) << 8 ) + wav_rec[0];
  520.  
  521. /*
  522. **  Next we should find the block type "WAVE".
  523. */
  524.     bytes = fread( (char *)wav_rec, (int)1, (int)4, wav_file );
  525.     if( ( bytes < 4 ) || memcmp( wav_rec, "WAVE", 4 ) )
  526.     {
  527.         fprintf(stderr, "\nThis is not a valid .wav file, it does not contain \"WAVE\".\n");
  528.         return( FAILURE );
  529.     }
  530.  
  531. /*
  532. **  Next we should find the block type "fmt ".
  533. */
  534.     bytes = fread( (char *)wav_rec, (int)1, (int)4, wav_file );
  535.     if( ( bytes < 4 ) || memcmp( wav_rec, "fmt ", 4 ) )
  536.     {
  537.         fprintf(stderr, "\nThis is not a valid .wav file, it does not contain \"fmt \".\n");
  538.         return( FAILURE );
  539.     }
  540.  
  541. /*
  542. **  Get the chunk length.
  543. */
  544.     bytes = fread( (char *)wav_rec, (int)1, (int)4, wav_file );
  545.     if( bytes < 4 )
  546.     {
  547.         fprintf(stderr, "\nThis is not a valid .wav file, invalid chunk length.\n");
  548.         return( FAILURE );
  549.     }
  550.     ck_len = (((((((uint32)wav_rec[3]) << 8 ) + wav_rec[2] ) << 8 )
  551.               + wav_rec[1]) << 8 ) + wav_rec[0];
  552.  
  553. /*
  554. **  Get the format information.
  555. */
  556.     bytes = fread( (char *)wav_rec, (int)1, (int)14, wav_file );
  557.     if( bytes < 14 )
  558.     {
  559.         fprintf(stderr, "\nThis is not a valid .wav file, invalid format data.\n");
  560.         return( FAILURE );
  561.     }
  562.  
  563.     fmt_tag = (((uint16)wav_rec[1]) << 8 ) + wav_rec[0];
  564.     channels = (((uint16)wav_rec[3]) << 8 ) + wav_rec[2];
  565.     sample_rate = (((((((uint32)wav_rec[7]) << 8 ) + wav_rec[6] ) << 8 )
  566.               + wav_rec[5]) << 8 ) + wav_rec[4];
  567.  
  568. /*
  569. **  Set sample rate related variables.
  570. */
  571.     if( sample_rate == 44100L )
  572.     {
  573.         sample_cnt_low = 10;
  574.         sample_cnt_high = 14;
  575.         sample_cnt_irg = 1000;
  576.         sample_cnt_bit = 74;
  577.         sample_cnt_bit_limit = 40;
  578.         sample_cnt_minimum = 6;
  579.     }
  580.     else
  581.     if( sample_rate == 22050 )
  582.     {
  583.         sample_cnt_low = 6;
  584.         sample_cnt_high = 7;
  585.         sample_cnt_irg = 500;
  586.         sample_cnt_bit = 37;
  587.         sample_cnt_bit_limit = 20;
  588.         sample_cnt_minimum = 3;
  589.     }
  590.     else
  591.     {
  592.         fprintf(stderr, "\nSample rates other than 22.050 and 44.100 not supported.\n");
  593.         return( FAILURE );
  594.     }
  595.  
  596.     fmt_tag = (((uint16)wav_rec[1]) << 8 ) + wav_rec[0];
  597.     if( fmt_tag != 0x0001 )
  598.     {
  599.         fprintf(stderr, "\nNot a PCM wave file, format 0x%.4x not supported.\n", fmt_tag);
  600.         return( FAILURE );
  601.     }
  602.     if( channels != 1 )
  603.     {
  604.         fprintf(stderr, "\nNot a MONO wave file, stereo and multi-channel files not supported.\n");
  605.         return( FAILURE );
  606.     }
  607.  
  608. /*
  609. **  Get the bits per sample information.
  610. */
  611.     bytes = fread( (char *)wav_rec, (int)1, (int)2, wav_file );
  612.     if( bytes < 2 )
  613.     {
  614.         fprintf(stderr, "\nThis is not a valid .wav file, invalid format data.\n");
  615.         return( FAILURE );
  616.     }
  617.  
  618.     bits_sample = (((uint16)wav_rec[1]) << 8 ) + wav_rec[0];
  619.  
  620.     if( bits_sample != 8 )
  621.     {
  622.         fprintf(stderr, "\nNot a sound file sampled at 8 bit, format not supported.\n");
  623.         return( FAILURE );
  624.     }
  625.  
  626. /*
  627. **  Next we should find the block type "data".
  628. */
  629.     bytes = fread( (char *)wav_rec, (int)1, (int)4, wav_file );
  630.     if( ( bytes < 4 ) || memcmp( wav_rec, "data", 4 ) )
  631.     {
  632.         fprintf(stderr, "\nThis is not a valid .wav file, it does not contain \"data\".\n");
  633.         return( FAILURE );
  634.     }
  635.  
  636. /*
  637. **  Get the chunk length.
  638. */
  639.     bytes = fread( (char *)wav_rec, (int)1, (int)4, wav_file );
  640.     if( bytes < 4 )
  641.     {
  642.         fprintf(stderr, "\nThis is not a valid .wav file, invalid chunk length.\n");
  643.         return( FAILURE );
  644.     }
  645.     pcm_ck_len = (((((((uint32)wav_rec[3]) << 8 ) + wav_rec[2] ) << 8 )
  646.               + wav_rec[1]) << 8 ) + wav_rec[0];
  647.  
  648.     fprintf(stderr, "\nMONO 8 bit PCM format.  Sampling rate is %lu Hz.\n", sample_rate);
  649.  
  650. /*
  651. **  Well, we finally hit the PCM sample data.
  652. **  This looks like what we wanted, so we will call this success.
  653. */
  654.  
  655.     return( SUCCESS );
  656. }
  657.  
  658. /*****************************************************************************
  659. **  NAME:  process_record()
  660. **
  661. **  PURPOSE:
  662. **      There is data in the count table.  This must now be interpreted.
  663. **      The count values are converted to the data they are representing.
  664. **
  665. **  DESCRIPTION:
  666. **      This function will take data from the count table and interpret it.
  667. **      Then this data is removed from the buffer to make room for new data.
  668. **      Data that is not processed when we leave this function is moved towards
  669. **      the start of the buffer in order to make room for the new data.
  670. **      We should get here every time a complete record has been stuffed into
  671. **      the table.
  672. **
  673. **  INPUT:
  674. **      Nothing.
  675. **      Data is taken from the sample count table.
  676. **
  677. **  OUTPUT:
  678. **      Data is output to the file.
  679. **      The table is reset to the beginning.
  680. **      The function returns nothing.
  681. **
  682. */
  683.  
  684. static void         process_record( void )
  685. {
  686.     uint32          bit_cnt;                /* Bit counter                  */
  687.     uint32          bit_len;                /* Length of one bit            */
  688.     uint32          bit_limit;              /* Length for recognizing bit   */
  689.     ubyte           byte;                   /* Byte decoded from fsk data   */
  690.     uint32          bytes;                  /* Number of bytes read         */
  691.     uint32          checksum;               /* Checksum of the record       */
  692.     uint32          cnt;                    /* Count of samples             */
  693.     uint32          cnt_sum;                /* Total sample counts for byte */
  694.     uint32          ctl_1_cnt;              /* Samples in control byte 1    */
  695.     uint32          ctl_2_cnt;              /* Samples in control byte 2    */
  696.     uint32          data_ndx;               /* Index for record data        */
  697.     uint32          ndx;                    /* Index into buffer            */
  698.     uint32          ndx_prwt;               /* end of record                */
  699.  
  700. /*
  701. **  If we only have a mark tone, this must be the leader of the tape.
  702. **  We should write out the leader to the file, but for now, we will simply
  703. **  ignore it.  It will be written with the first record.
  704. */
  705.     if( sample_tbl_ndx == 0 )
  706.         return;
  707.  
  708.     bytes = 0;
  709.  
  710.     PRINT( ("\nIn process_record() sample_tbl_ndx = %lu\n", sample_tbl_ndx) );
  711.     PRINT( ("Now cleaning up glitches.\n") );
  712.  
  713. /*
  714. **  Output the table to the FSK file and the diagnostics data.
  715. */
  716.     for( ndx = 0; ndx <= sample_tbl_ndx; ndx++ )
  717.     {
  718.         PRINT( ("ndx %lu Position %lu Mark %lu, Space %lu.\n", ndx,
  719.                 sample_cnt_tbl[ndx].sample_pos,
  720.                 sample_cnt_tbl[ndx].sample_cnt_mark,
  721.                 sample_cnt_tbl[ndx].sample_cnt_space ) );
  722.  
  723. /*
  724. **  Output the table to the FSK file.
  725. **  The last space count was not finished yet, so we will have to print that
  726. **  the next time we print the table.  The last thing we print is the
  727. **  last mark count, so do not print that the next time.  Of course all
  728. **  this is not applied for the very first and very last time we print
  729. **  the contents of the table.
  730. */
  731.         if( fsk )
  732.         {
  733.             if( ndx < sample_tbl_ndx )
  734.             {
  735.                 if( ( ndx == 0 ) && ( fsk_print_first == FALSE ) )
  736.                 {                   /* First pair of table  */
  737.                     fprintf( fsk_file, "%.5lu\n",
  738.                         sample_cnt_tbl[ndx].sample_cnt_space );
  739.                 }
  740.                 else
  741.                 {                   /* First time around or regular pair */
  742.                     fprintf( fsk_file, "%.8lu %.5lu %.5lu\n",
  743.                         sample_cnt_tbl[ndx].sample_pos,
  744.                         sample_cnt_tbl[ndx].sample_cnt_mark,
  745.                         sample_cnt_tbl[ndx].sample_cnt_space );
  746.                     fsk_print_first = FALSE;
  747.                 }
  748.             } /* end if not at end of table */
  749.             else
  750.             {                       /* Last pair in table   */
  751.                 if( cnt_cur )       /* Not yet end of file? */
  752.                 {
  753.                     fprintf( fsk_file, "%.8lu %.5lu ",
  754.                         sample_cnt_tbl[ndx].sample_pos,
  755.                         sample_cnt_tbl[ndx].sample_cnt_mark );
  756.                 }
  757.                 else
  758.                 {                   /* end of file, flush all */
  759.                     fprintf( fsk_file, "%.8lu %.5lu %.5lu\n",
  760.                         sample_cnt_tbl[ndx].sample_pos,
  761.                         sample_cnt_tbl[ndx].sample_cnt_mark,
  762.                         sample_cnt_tbl[ndx].sample_cnt_space );
  763.                 }
  764.             } /* end else if not at end of table */
  765.         } /* end if fsk data requested */
  766.     } /* end for all table entries */
  767.  
  768. /*
  769. **  If things worked the way they were designed, we should have one complete
  770. **  record in the table now.  It starts out with the Pre Record Write Tone.
  771. **  Before we start processing, first clean up glitches.
  772. **  Mark and space tones that are very short should be ignored.  We add their
  773. **  count to the preceeding count.
  774. **  Maybe we should first see how many glitches there are, possibly disposing
  775. **  of this entire record as noise in the leader or PRWT.
  776. **  Since our record should start out with a very long mark tone, we will
  777. **  assume that this first mark tone is fine.
  778. */
  779.     ndx_prwt = sample_tbl_ndx;
  780.  
  781.     for( ndx = 0; ndx < sample_tbl_ndx; )
  782.     {
  783.         if( ndx && ( sample_cnt_tbl[ndx].sample_cnt_mark > sample_cnt_irg ) )
  784.         {
  785.             ndx_prwt = ndx;
  786.             break;
  787.         }
  788.  
  789. /*
  790. **  If the current space count is too low, add it, and the next mark count to
  791. **  the current mark count, move the next space count to the current space
  792. **  count, and move up the rest of the table.
  793. **  However, if the next mark count is also too low, add this space count
  794. **  and the next mark count to the next space count.  We can do this by
  795. **  adding the next mark count and the next space count to the current space
  796. **  count, and then move up the rest of the table.
  797. */
  798.         if( sample_cnt_tbl[ndx].sample_cnt_space < sample_cnt_bit_limit )
  799.         {
  800.             if( sample_cnt_tbl[ndx + 1].sample_cnt_mark < sample_cnt_bit_limit )
  801.             {
  802.                 sample_cnt_tbl[ndx].sample_cnt_space +=
  803.                 sample_cnt_tbl[ndx + 1].sample_cnt_mark +
  804.                 sample_cnt_tbl[ndx + 1].sample_cnt_space;
  805.             }
  806.             else
  807.             {
  808.                 sample_cnt_tbl[ndx].sample_cnt_mark +=
  809.                 sample_cnt_tbl[ndx].sample_cnt_space +
  810.                 sample_cnt_tbl[ndx + 1].sample_cnt_mark;
  811.                 sample_cnt_tbl[ndx].sample_cnt_space =
  812.                 sample_cnt_tbl[ndx + 1].sample_cnt_space;
  813.             }
  814.  
  815. /*
  816. **  Move the sample counts after the next one up by one.
  817. */
  818.             if( ndx + 1 < sample_tbl_ndx )
  819.             {
  820.                 memcpy( &(sample_cnt_tbl[ndx + 1]),
  821.                         &(sample_cnt_tbl[ndx + 2]),
  822.                         (sample_tbl_ndx - ndx - 1) * sizeof(sample_cnt_blk) );
  823.             }
  824.             sample_tbl_ndx--;
  825.             ndx_prwt = sample_tbl_ndx;
  826.             continue; /* Make sure it is fine now */
  827.         }
  828.  
  829. /*
  830. **  If the next mark count is too low, add it, and the next space count to
  831. **  the current space count, and move up the rest of the table.
  832. */
  833.         if( sample_cnt_tbl[ndx + 1].sample_cnt_mark < sample_cnt_bit_limit )
  834.         {
  835.             sample_cnt_tbl[ndx].sample_cnt_space +=
  836.             sample_cnt_tbl[ndx + 1].sample_cnt_mark +
  837.             sample_cnt_tbl[ndx + 1].sample_cnt_space;
  838.  
  839. /*
  840. **  Move the sample counts after the next one up by one.
  841. */
  842.             if( ndx + 1 < sample_tbl_ndx )
  843.             {
  844.                 memcpy( &(sample_cnt_tbl[ndx + 1]),
  845.                         &(sample_cnt_tbl[ndx + 2]),
  846.                         (sample_tbl_ndx - ndx - 1) * sizeof(sample_cnt_blk) );
  847.             }
  848.             sample_tbl_ndx--;
  849.             ndx_prwt = sample_tbl_ndx;
  850.             continue; /* Make sure it is fine now */
  851.         }
  852.  
  853. /*
  854. **  This sample count is fine, move to the next one.
  855. */
  856.         ndx++;
  857.     }
  858.  
  859.     if( diagnostics )
  860.     {
  861.         printf("Done cleaning up glitches. %lu elements to process.\n", ndx_prwt);
  862.         for( ndx = 0; ndx <= ndx_prwt; ndx++ )
  863.         {
  864.             printf("ndx %lu Position %lu Mark %lu, Space %lu.\n", ndx,
  865.                 sample_cnt_tbl[ndx].sample_pos,
  866.                 sample_cnt_tbl[ndx].sample_cnt_mark,
  867.                 sample_cnt_tbl[ndx].sample_cnt_space );
  868.         }
  869.     }
  870.  
  871. /*
  872. **  The table starts with a Pre-Record Write Tone.
  873. **  A bit is about 73.5 samples if the sample rate is 44.100.
  874. **  We need 73.5 samples to form a single bit.  However, the tape
  875. **  may not be coded at 600 baud.
  876. **  We have to allow for some tolerance in the baudrate.
  877. **  We need to detect the baudrate now.
  878. **  Each record starts out with two marker bytes with a value of 0x55.
  879. **  We will use these bytes to detect the baudrate, since that is what they
  880. **  were intended to be used for.
  881. **  Note that some tapes have a weird format, in which these two marker bytes
  882. **  might not be present, so if we do not find them, we cannot be sure that
  883. **  this stuff is noise in that case.
  884. */
  885.     if( ndx_prwt < 5 )
  886.     {
  887.  
  888. /*
  889. **  Glitch in the PRWT, ignore this stuff.
  890. */
  891.         bit_len = 1;
  892.         bit_limit = bit_len * 55 / 100;
  893.     }
  894.     else
  895.     if( ndx_prwt < 10 )
  896.     {
  897.  
  898. /*
  899. **  Might be one of these weird formats, probably a couple of checksum bytes.
  900. */
  901.         bit_len = sample_cnt_bit;
  902.         bit_limit = bit_len * 55 / 100;
  903.     }
  904.     else
  905.     {
  906.  
  907. /*
  908. **  We should find the two marker bytes at the beginning of the record.
  909. **  They consist of 10 alternating bits each, so we compute the sum of the
  910. **  first 20 mark and space counts, which should be 20 bits.  If we divide
  911. **  this sum by 20, we know the length of one bit.
  912. */
  913.         ctl_1_cnt = sample_cnt_tbl[0].sample_cnt_space +
  914.                     sample_cnt_tbl[1].sample_cnt_mark  +
  915.                     sample_cnt_tbl[1].sample_cnt_space +
  916.                     sample_cnt_tbl[2].sample_cnt_mark  +
  917.                     sample_cnt_tbl[2].sample_cnt_space +
  918.                     sample_cnt_tbl[3].sample_cnt_mark  +
  919.                     sample_cnt_tbl[3].sample_cnt_space +
  920.                     sample_cnt_tbl[4].sample_cnt_mark  +
  921.                     sample_cnt_tbl[4].sample_cnt_space +
  922.                     sample_cnt_tbl[5].sample_cnt_mark;
  923.         ctl_2_cnt = sample_cnt_tbl[5].sample_cnt_space +
  924.                     sample_cnt_tbl[6].sample_cnt_mark  +
  925.                     sample_cnt_tbl[6].sample_cnt_space +
  926.                     sample_cnt_tbl[7].sample_cnt_mark  +
  927.                     sample_cnt_tbl[7].sample_cnt_space +
  928.                     sample_cnt_tbl[8].sample_cnt_mark  +
  929.                     sample_cnt_tbl[8].sample_cnt_space +
  930.                     sample_cnt_tbl[9].sample_cnt_mark  +
  931.                     sample_cnt_tbl[9].sample_cnt_space +
  932.                     sample_cnt_tbl[10].sample_cnt_mark;
  933.  
  934.         bit_len = ( ctl_1_cnt + ctl_2_cnt ) / 20;
  935.  
  936. /*
  937. **  If the bit length gets a strange value, the record probably did not
  938. **  start with two marker bytes, we will assume the default baudrate.
  939. */
  940.         if( ( bit_len <= sample_cnt_bit * 70 / 100 ) ||
  941.             ( bit_len >= sample_cnt_bit * 120 / 100 ) )
  942.             bit_len = sample_cnt_bit;
  943.         bit_limit = bit_len * 55 / 100;
  944.     }
  945.  
  946.     PRINT( ("At %.8ld bit length = %lu, baudrate = %lu.\n",
  947.                 cnt_total, bit_len, sample_rate / bit_len ) );
  948.  
  949.     if( ( bit_len > sample_cnt_bit * 70 / 100 ) &&
  950.         ( bit_len < sample_cnt_bit * 120 / 100 ) )
  951.     {
  952.         fprintf( stderr,
  953.                  "At %.8ld bit length = %lu samples, baudrate = %lu baud.\n",
  954.                  cnt_total, bit_len, sample_rate / bit_len );
  955.  
  956. /*
  957. **  Write out the data to the cassette file.
  958. **  Put the length of the PRWT into the aux-bytes.
  959. */
  960.         memcpy( cas_rec.cas_record_id, "data", 4 );
  961.         cas_rec.cas_len_lo = 0;
  962.         cas_rec.cas_len_hi = 0;
  963.         cas_rec.cas_aux1 =  (( sample_cnt_tbl[0].sample_cnt_mark * 1000 ) / sample_rate ) % 256;
  964.         cas_rec.cas_aux2 =  (( sample_cnt_tbl[0].sample_cnt_mark * 1000 ) / sample_rate ) / 256;
  965.  
  966.         data_ndx = 0;
  967.  
  968.         for( ndx = 0; ndx < ndx_prwt; )
  969.         {
  970.  
  971. /*
  972. **  A byte consists of 8 data bits, a startbit and a stopbit.
  973. **  See how many bits are represented by the sample count.
  974. */
  975.             byte = 0x00;
  976.             cnt_sum = 0;
  977.             PRINT( ("Offset %lu ndx %lu ", sample_cnt_tbl[ndx].sample_pos,
  978.                     ndx ) );
  979.             for( bit_cnt = 0; bit_cnt < 10; )
  980.             {
  981.                 cnt = sample_cnt_tbl[ndx].sample_cnt_space;
  982.                 cnt_sum += cnt;
  983.                 PRINT( (" %lu ", cnt ) );
  984.                 while( cnt > bit_limit )
  985.                 {
  986.                     if( cnt > bit_len )
  987.                         cnt -= bit_len;
  988.                     else
  989.                         cnt = 0;
  990.                     if( bit_cnt )           /* Ignore startbit */
  991.                     {
  992.                         byte = byte >> 1;   /* Make room for next bit */
  993.                         byte &= 0x7F;       /* Add a zero bit         */
  994.                         PRINT( ("0") );
  995.                     }
  996.                     bit_cnt++;
  997.                     if( bit_cnt == 10 )     /* Quit when we hit the stopbit */
  998.                         break;
  999.                 } /* End while processing space count */
  1000.                 ndx++;
  1001.                 cnt = sample_cnt_tbl[ndx].sample_cnt_mark;
  1002.                 cnt_sum += cnt;
  1003.                 PRINT( (" %lu ", cnt ) );
  1004.                 while( cnt > bit_limit )
  1005.                 {
  1006.                     if( cnt > bit_len )
  1007.                         cnt -= bit_len;
  1008.                     else
  1009.                         cnt = 0;
  1010.                     if( bit_cnt < 9 )       /* Ignore stopbit         */
  1011.                     {
  1012.                         byte = byte >> 1;   /* Make room for next bit */
  1013.                         byte |= 0x080;      /* Add a one bit          */
  1014.                         PRINT( ("1") );
  1015.                     }
  1016.                     bit_cnt++;
  1017.                     if( bit_cnt == 10 )     /* Quit when we hit the stopbit */
  1018.                         break;
  1019.                 } /* End while processing mark count */
  1020.             } /* End for 10 bits */
  1021.             PRINT( ("\nByte %.2x sum %lu.\n", byte, cnt_sum ) );
  1022.             cas_rec.cas_data[data_ndx++] = byte;
  1023.             bytes++;
  1024.         } /* end for all pairs up to next PRWT */
  1025.  
  1026.         cas_rec.cas_len_hi = data_ndx / 256;
  1027.         cas_rec.cas_len_lo = data_ndx % 256;
  1028.         fwrite( &cas_rec, 1,
  1029.                 cas_rec.cas_len_hi * 256 + cas_rec.cas_len_lo + 8, cas_file );
  1030.  
  1031. /*
  1032. **  Print the hex values.
  1033. **  Start out with the PRWT length and the record length.
  1034. */
  1035.         fprintf( hex_file, "%.5lu %lu",
  1036.         ( sample_cnt_tbl[0].sample_cnt_mark * 1000 ) / sample_rate, bytes );
  1037.         checksum = 0;
  1038.         for( ndx = 0; ndx < data_ndx; ndx++ )
  1039.         {
  1040.             fprintf( hex_file, " %.2x", cas_rec.cas_data[ndx] );
  1041.             if( ndx < data_ndx - 1 )
  1042.             {
  1043.                 checksum += cas_rec.cas_data[ndx];
  1044.                 if( checksum > 0x0ff )  /* If carry */
  1045.                 {
  1046.                     checksum &= 0x0ff;  /* Wrap around */
  1047.                     checksum++;         /* Add carry back in */
  1048.                 }
  1049.              }
  1050.         } /* end for all bytes in the block */
  1051.         fprintf( hex_file, " %.2lx %s\n", checksum,
  1052.                  ( checksum == cas_rec.cas_data[data_ndx - 1] ) ? "ok" : "bad" );
  1053.  
  1054.         if( diagnostics )
  1055.         {
  1056.             if( checksum != cas_rec.cas_data[data_ndx - 1] )
  1057.                 printf("\nBad checksum!\n");
  1058.             printf( "PRWT is %lu milliseconds.\n", sample_cnt_tbl[0].sample_cnt_mark / 44 );
  1059.         }
  1060.  
  1061. /*
  1062. **  Move the remaining portion of the buffer to the beginning of the buffer.
  1063. **  Cleaning up the table might have caused the PRWT to be not the last
  1064. **  element in the table, so take note of this when moving the table.
  1065. */
  1066.         if( sample_tbl_ndx )
  1067.         {
  1068.             if( sample_tbl_ndx > ndx_prwt )
  1069.             {
  1070.                 ndx = sample_tbl_ndx - ndx_prwt + 1;
  1071.                 memcpy( &(sample_cnt_tbl[0]),
  1072.                         &(sample_cnt_tbl[ndx_prwt]),
  1073.                         sizeof(sample_cnt_blk) * ndx);
  1074.                 sample_tbl_ndx = ndx - 1;
  1075.             }
  1076.             else
  1077.             {
  1078.                 memcpy( &(sample_cnt_tbl[0]),
  1079.                         &(sample_cnt_tbl[sample_tbl_ndx]),
  1080.                         sizeof(sample_cnt_blk) );
  1081.                 sample_tbl_ndx = 0;
  1082.             }
  1083.         }
  1084.     } /* end if baudrate acceptable */
  1085.     else
  1086.     {
  1087.         fprintf( stderr,
  1088.                  "At %.8ld skipping noise or bad data.\n",
  1089.                  cnt_total );
  1090.  
  1091. /*
  1092. **  Must have been noise, add it all and consider it prwt.
  1093. */
  1094.         if( sample_tbl_ndx )
  1095.         {
  1096.             for( ndx = 0; ndx < ndx_prwt; ndx++ )
  1097.             {
  1098.                 sample_cnt_tbl[ndx_prwt].sample_cnt_mark +=
  1099.                 sample_cnt_tbl[ndx].sample_cnt_mark +
  1100.                 sample_cnt_tbl[ndx].sample_cnt_space;
  1101.             }
  1102.             ndx = sample_tbl_ndx - ndx_prwt + 1;
  1103.             memcpy( &(sample_cnt_tbl[0]),
  1104.                     &(sample_cnt_tbl[ndx_prwt]),
  1105.                     sizeof(sample_cnt_blk) * ndx);
  1106.             sample_tbl_ndx = 0;
  1107.         }
  1108.     }
  1109.  
  1110.     PRINT( ("Leaving process_record() with %lu bytes processed.\n", bytes ) );
  1111.  
  1112. }
  1113.  
  1114. /*****************************************************************************
  1115. **  NAME:  replenish_buffer()
  1116. **
  1117. **  PURPOSE:
  1118. **      Keep the buffer filled with PCM data.
  1119. **
  1120. **  DESCRIPTION:
  1121. **      This function will read data from the wave file and store it in the
  1122. **      PCM buffer.  Data that was still left in the buffer is moved towards
  1123. **      the start of the buffer in order to make room for the new data.
  1124. **
  1125. **  INPUT:
  1126. **      Nothing.
  1127. **      Data is read from the wave file.
  1128. **
  1129. **  OUTPUT:
  1130. **      Data is stored in the buffer.
  1131. **      Buffer status is updated.
  1132. **      The function returns nothing.
  1133. **
  1134. */
  1135.  
  1136. static void         replenish_buffer( void )
  1137. {
  1138.     uint32          bytes;                  /* Number of bytes read         */
  1139.     uint32          rest_len;               /* Remaining bytes in buffer    */
  1140.     ubyte           wav_rec[PCM_BUF_HALF];  /* Buffer for reading wave data */
  1141.  
  1142. /*
  1143. **  Replenish buffer.
  1144. **  Move the remaining portion of the buffer to the beginning of the buffer.
  1145. **  The buffer end points to just beyond the last byte of the buffer.
  1146. */
  1147.     if( pcm_ndx && pcm_ndx_end )
  1148.     {
  1149.         if( pcm_ndx > pcm_ndx_end )
  1150.         {
  1151.             fprintf( stderr, "\nPanic: Beyond end of buffer.\n");
  1152.             getchar();
  1153.         }
  1154.         else
  1155.         {
  1156.             rest_len = pcm_ndx_end - pcm_ndx;
  1157.             memcpy( pcm, &pcm[pcm_ndx], rest_len );
  1158.             pcm_ndx = 0;
  1159.             pcm_ndx_end = rest_len;
  1160.         }
  1161.     }
  1162.  
  1163. /*
  1164. **  Get some more bytes and stuff them into the PCM buffer.
  1165. */
  1166.     bytes = PCM_BUF_HALF;
  1167.     bytes = fread( (char *)wav_rec, (int)1, (int)bytes, wav_file );
  1168.     if( bytes )
  1169.     {
  1170.         memcpy( &pcm[pcm_ndx_end], wav_rec, bytes );
  1171.         pcm_ndx_end += bytes;
  1172.         pcm_bytes += bytes;
  1173.     }
  1174. }
  1175.  
  1176. /*****************************************************************************
  1177. **  NAME:  usage()
  1178. **
  1179. **  PURPOSE:
  1180. **      Display the command line format for the program.
  1181. **
  1182. **  DESCRIPTION:
  1183. **      This function will explain the usage of the program to the user.
  1184. **      The program name is taken from the first command line argument.
  1185. **
  1186. **  INPUT:
  1187. **      - The address of the command line, containing the program name.
  1188. **
  1189. **  OUTPUT:
  1190. **      The usage is displayed on the terminal.
  1191. **      The function returns nothing.
  1192. **
  1193. */
  1194.  
  1195. static void         usage( cmd )
  1196. char * cmd;                         /* Program name                     */
  1197. {
  1198.     char * whoami;      /* For searching program name in command line   */
  1199.     char * name;        /* Pointer to actual program name in command    */
  1200.     int    len;         /* Length of program name                       */
  1201.     int    found_dot;   /* Nonzero if we found a dot in the name        */
  1202.  
  1203. /*
  1204. **  Get program name and print usage message.
  1205. **  The complete pathname including extension is part of the first
  1206. **  argument as passed by the operating system.
  1207. */
  1208.     for( whoami = cmd, len = 0, found_dot = 0; *whoami; whoami++ )
  1209.     {
  1210.         if( *whoami == '.' )
  1211.         {
  1212.             found_dot = 1;
  1213.             continue;
  1214.         }
  1215.         if( *whoami == '\\' )   /* if this was part of the path, */
  1216.         {
  1217.             name = whoami + 1;  /* record position */
  1218.             len = 0;            /* then restart counting length */
  1219.             found_dot = 0;
  1220.             continue;
  1221.         }
  1222.         if( *whoami == ' ' )    /* end of name found            */
  1223.             break;
  1224.         if( found_dot )         /* skip .exe or .com stuff      */
  1225.             continue;
  1226.         len++;                  /* Increment program name length */
  1227.     }
  1228.  
  1229. /*
  1230. **  Let me explain...
  1231. */
  1232.     fprintf(stderr, "\nUsage: %.*s [wavefile] [\"description\"] [/d] [/f]\n", len, name);
  1233.     fprintf(stderr, "to convert a .wav file to a .cas cassette image.\n\n");
  1234.     fprintf(stderr, "wavefile      an Atari classic tape sampled at 44.100.\n");
  1235.     fprintf(stderr, "description   descriptive text entered as a quoted string.\n\n");
  1236.     fprintf(stderr, "/d            to print diagnostic information.\n");
  1237.     fprintf(stderr, "/f            to write the FSK table file.\n");
  1238.     fprintf(stderr, "Refer to the documentation for more information.\n");
  1239.  
  1240.     return;
  1241. }
  1242.  
  1243. /*****************************************************************************
  1244. **  NAME:  wav2fsk()
  1245. **
  1246. **  PURPOSE:
  1247. **      Read data from the .wav file and convert it to levels recognized
  1248. **      as fsk mark and space values.
  1249. **      The number of samples within one half period is counted.  Based on
  1250. **      this, we can determine the frequency of the sound, and thus we can
  1251. **      distinguish between mark and space levels.  The output routine is
  1252. **      then called to print this number of samples.
  1253. **      The number of samples of this level are recorded for interpretation.
  1254. **      If we have a complete record in the buffer, we can try to interpret
  1255. **      the bits in the buffer.
  1256. **
  1257. **  DESCRIPTION:
  1258. **      This function will read the data and process it.
  1259. **
  1260. **  INPUT:
  1261. **      Nothing.
  1262. **
  1263. **  OUTPUT:
  1264. **      Prints results.
  1265. **      Returns SUCCESS if data converted successfully.
  1266. **      Returns FAILURE if some error occurred.
  1267. **
  1268. */
  1269.  
  1270. static uint32       wav2fsk( void )
  1271. {
  1272.     uint16          level;                  /* Interpreted level of signal  */
  1273.  
  1274.     cnt_total = 0;
  1275.  
  1276. /*
  1277. **  Set pointers to point to the end of the buffer.
  1278. */
  1279.     pcm_cnt = 0;
  1280.     pcm_ndx = 0;
  1281.     pcm_ndx_end = 0;
  1282.  
  1283. /*
  1284. **  Initialize sample count table.
  1285. */
  1286.     sample_tbl_ndx = 0;
  1287.     sample_tbl_level = FSK_MARK;
  1288.     sample_cnt_tbl[0].sample_pos = 0;
  1289.     sample_cnt_tbl[0].sample_cnt_mark = 0;
  1290.  
  1291. /*
  1292. **  Load the buffer.
  1293. */
  1294.     replenish_buffer();
  1295.     replenish_buffer();
  1296.  
  1297.     if( pcm[1] > pcm[0] )
  1298.     {
  1299.         pcm_level_previous = 0;
  1300.         pcm_level_rising = TRUE;
  1301.     }
  1302.     else
  1303.     {
  1304.         pcm_level_previous = 255;
  1305.         pcm_level_rising = FALSE;
  1306.     }
  1307.  
  1308.     period_sample_cnt();
  1309.     period_sample_cnt();
  1310.     while( cnt_cur )
  1311.     {
  1312.         if( ( cnt_cur >= sample_cnt_low ) && ( cnt_cur <= sample_cnt_high ) )
  1313.             level = FSK_SPACE;
  1314.         else
  1315.             level = FSK_MARK;
  1316.  
  1317.         process_cnt( cnt_val, level );
  1318.  
  1319.         period_sample_cnt();
  1320.     } /* end while */
  1321.     process_record();
  1322.     printf("\n");
  1323.  
  1324.     return( SUCCESS );
  1325. }
  1326.  
  1327. /*****************************************************************************
  1328. ==  EXPORTED FUNCTIONS
  1329. *****************************************************************************/
  1330.  
  1331. /*****************************************************************************
  1332. **  NAME:  MAIN()
  1333. **
  1334. **  PURPOSE:
  1335. **      An entry point for testing or running this utility.
  1336. **
  1337. **  DESCRIPTION:
  1338. **      Prompt for the file to open and then go process it.
  1339. **
  1340. **  INPUT:
  1341. **      argc and argv.
  1342. **
  1343. **  OUTPUT:
  1344. **      Returns an int as it should.
  1345. **
  1346. */
  1347. int                 main( argc, argv )
  1348. int                 argc;               /* Command line argument count  */
  1349. char              * argv[];             /* Command line argument ptrs   */
  1350. {
  1351.     ubyte           answer;                 /* Response to yes/no question  */
  1352.     uint32          arg_ndx;                /* Argument number index        */
  1353.     uint32          arg_no;                 /* Argument number              */
  1354.     uint32          wrk_ndx;                /* Work index                   */
  1355.     ubyte           desc[80];               /* Description of cassette tape */
  1356.     uint16          desc_len;               /* Length of the description    */
  1357.     bool            end_of_str;             /* Null terminator seen?        */
  1358.     ubyte           input_path[PATH_LEN];   /* Input wave file spec         */
  1359.     ubyte           fsk_path[PATH_LEN];     /* Output fsk file spec         */
  1360.     ubyte           hex_path[PATH_LEN];     /* Output hex file spec         */
  1361.     ubyte           cas_path[PATH_LEN];     /* Output cas file spec         */
  1362.     ubyte           buf[BUF_LEN];           /* Buffer string                */
  1363.     uint32          stat;                   /* Status from function         */
  1364.     ubyte           proceed;                /* Proceed with conversion      */
  1365.  
  1366. /*
  1367. **  Allocate buffer space for the sample count table.
  1368. */
  1369.     sample_cnt_tbl = (sample_cnt_blk *)
  1370.                      malloc((unsigned long)SAMPLE_CNT_TBL_LEN *
  1371.                             sizeof( sample_cnt_blk ) );
  1372.  
  1373.  
  1374.     if( !sample_cnt_tbl )
  1375.     {
  1376.         fprintf( stderr, "\nCannot allocate buffer, insufficient memory.\n" );
  1377.         exit( 255 );
  1378.     }
  1379.  
  1380. /*
  1381. **  Process command line arguments.
  1382. **  We do not treat the options switch as an argument.  It may be placed
  1383. **  anywhere on the command line.  So we have to count the arguments ourselves
  1384. **  so that we know what argument we are processing.
  1385. */
  1386.     arg_no = 0;
  1387.     diagnostics = FALSE;
  1388.     fsk = FALSE;
  1389.     desc_len = 0;
  1390.  
  1391.     for( arg_ndx = 1; arg_ndx < argc; arg_ndx++ )
  1392.     {
  1393.  
  1394. /*
  1395. **  If we encounter the options switch, process the options.
  1396. **  The options must start with a slash.
  1397. */
  1398.         if( argv[arg_ndx][0] == '/' )
  1399.         {
  1400.  
  1401.             for( wrk_ndx = 0; argv[arg_ndx][wrk_ndx]; wrk_ndx++ )
  1402.             {
  1403.  
  1404. /*
  1405. **  If the user is confused, seeking help, she/he should read the * manual.
  1406. **  We can give them a hint though.
  1407. */
  1408.                 if( argv[arg_ndx][wrk_ndx] == '?' )
  1409.                 {
  1410.                     usage( argv[0] );
  1411.                     exit( 0 );
  1412.                 }
  1413.  
  1414. /*
  1415. **  The /d option selects the diagnostics output.
  1416. */
  1417.                 if( toupper( argv[arg_ndx][wrk_ndx] ) == 'D' )
  1418.                 {
  1419.                     diagnostics = TRUE;
  1420.                     continue;
  1421.                 }
  1422.  
  1423. /*
  1424. **  The /f option selects the fsk table output.
  1425. */
  1426.                 if( toupper( argv[arg_ndx][wrk_ndx] ) == 'F' )
  1427.                 {
  1428.                     fsk = TRUE;
  1429.                     continue;
  1430.                 }
  1431.  
  1432. /*
  1433. **  Ignore other options.
  1434. */
  1435.                 continue;
  1436.             } /* end for all characters after options switch */
  1437.  
  1438. /*
  1439. **  No further processing for the options switches.
  1440. */
  1441.             continue;
  1442.         } /* end if options switch */
  1443.         arg_no++;
  1444.  
  1445. /*
  1446. **  First argument is the file spec.
  1447. */
  1448.         if( arg_no == 1 )
  1449.         {
  1450.             for ( wrk_ndx = 0, end_of_str = FALSE;
  1451.                 wrk_ndx < PATH_LEN; wrk_ndx++ )
  1452.             {
  1453.                 if ( argv[arg_ndx][wrk_ndx] == '\0' ) /* End of argument string?            */
  1454.                     end_of_str = TRUE;
  1455.                 if ( end_of_str )
  1456.                     input_path[wrk_ndx] = '\0';
  1457.                 else
  1458.                     input_path[wrk_ndx] = toupper( argv[arg_ndx][wrk_ndx] );
  1459.             }
  1460.  
  1461.             wav_file = fopen( (char *)input_path, "rb" );
  1462.             if( wav_file == NULL )
  1463.             {
  1464.                 fprintf(stderr, "Cannot open wave file %s\n", input_path);
  1465.                 exit( 255 );
  1466.             }
  1467.         }
  1468.  
  1469. /*
  1470. **  Optionally, the description can be entered as the second command line
  1471. **  argument.  This should be done as a quoted string, since that is the
  1472. **  way command line arguments work.
  1473. */
  1474.         if( arg_no ==  2 )
  1475.         {
  1476.             desc_len = STRLEN( argv[arg_ndx] );
  1477.             if( desc_len > 80 )
  1478.                 desc_len = 80;
  1479.             memcpy( desc, argv[arg_ndx], desc_len );
  1480.         } /* end if description argument */
  1481.     } /* end for all command line arguments */
  1482.  
  1483. /*
  1484. **  If there is no filename on the command line, ask for it.
  1485. */
  1486.     if( arg_no == 0 )
  1487.     {
  1488.  
  1489. /*
  1490. **  Open hailing frequencies.
  1491. **  No command line arguments, so ask what it is we have to do.
  1492. */
  1493.         printf( "\n\nClassic Atari cassette tape recovery version April 20, 1997\n" );
  1494.         printf( "\n\nCopyright 1996, 1997 by Ernest R. Schreurs\n" );
  1495.         printf( "\n\nAll rights reserved\n" );
  1496.  
  1497.  
  1498.         while( TRUE )                       /* until terminated by control Z*/
  1499.         {
  1500.             printf( "\nEnter ^Z or hit Control Z to terminate\n" );
  1501.  
  1502.             do                              /* until .wav file entered    */
  1503.             {
  1504.                 printf("\nEnter .wav file to be converted : ");
  1505.                 GET_BUF();
  1506.  
  1507.                 for ( wrk_ndx = 0, end_of_str = FALSE;
  1508.                     wrk_ndx < PATH_LEN; wrk_ndx++ )
  1509.                 {
  1510.                     if ( wrk_ndx < BUF_LEN )
  1511.                     {
  1512.                         if ( buf[wrk_ndx] == '\n' ) /* End of inputted string?      */
  1513.                             end_of_str = TRUE;
  1514.                         if ( buf[wrk_ndx] == '\0' ) /* Overkill, End marked by \n   */
  1515.                             end_of_str = TRUE;
  1516.                         if ( end_of_str )
  1517.                             input_path[wrk_ndx] = '\0';
  1518.                         else
  1519.                             input_path[wrk_ndx] = toupper( buf[wrk_ndx] );
  1520.                     }
  1521.                 }
  1522.             } while ( input_path[0] == ' ' );
  1523.  
  1524.             do                              /* until answer is Y or N       */
  1525.             {
  1526.                 printf("\nLoading file %s\n", input_path);
  1527.                 printf("\nIs this correct Y)es or N)o : ");
  1528.                 GET_BUF();
  1529.                 proceed = toupper( buf[0] );
  1530.  
  1531. /*
  1532. **  If blank, default is correct
  1533. */
  1534.                 if ( proceed == '\n' )
  1535.                     proceed = 'Y';
  1536.  
  1537.             } while ( proceed != 'Y' && proceed != 'N' );
  1538.  
  1539.             if ( proceed == 'N' )
  1540.                 continue;
  1541.  
  1542.             do                              /* until answer is Y or N       */
  1543.             {
  1544.                 printf("\nPrint diagnostic data Y)es or N)o : ");
  1545.                 GET_BUF();
  1546.                 answer = toupper( buf[0] );
  1547.  
  1548. /*
  1549. **  If blank, default is correct
  1550. */
  1551.                 if ( answer == '\n' )
  1552.                     answer = 'Y';
  1553.  
  1554.             } while ( answer != 'Y' && answer != 'N' );
  1555.  
  1556.             diagnostics = ( answer == 'Y' ) ? TRUE : FALSE;
  1557.  
  1558.             printf( "\nLoading data from wave file.\n" );
  1559.  
  1560.             wav_file = fopen( (char *)input_path, "rb" );
  1561.             if( wav_file == NULL )
  1562.             {
  1563.                 fprintf(stderr, "Cannot open wave file\n");
  1564.                 continue;
  1565.             }
  1566.             break;
  1567.         } /* end while need a valid filename */
  1568.  
  1569.         printf("\nEnter description : ");
  1570.         GET_BUF();
  1571.  
  1572.         for ( wrk_ndx = 0, desc_len = 0, end_of_str = FALSE;
  1573.               wrk_ndx < 80; wrk_ndx++ )
  1574.         {
  1575.             if ( wrk_ndx < BUF_LEN )
  1576.             {
  1577.                 if ( buf[wrk_ndx] == '\n' ) /* End of inputted string?      */
  1578.                     end_of_str = TRUE;
  1579.                 if ( buf[wrk_ndx] == '\0' ) /* Overkill, End marked by \n   */
  1580.                     end_of_str = TRUE;
  1581.             }
  1582.             if ( end_of_str )
  1583.                 desc[wrk_ndx] = '\0';
  1584.             else
  1585.             {
  1586.                 desc[wrk_ndx] = buf[wrk_ndx];
  1587.                 desc_len++;
  1588.             }
  1589.         }
  1590.     } /* end else if command line arguments */
  1591.  
  1592. /*
  1593. **  Process the header of the .wav file.
  1594. */
  1595.     stat = process_header();
  1596.     if( stat == FAILURE )
  1597.         exit( 255 );
  1598.  
  1599.     PRINT( ("File : %s\n", input_path ) );
  1600.  
  1601.     memcpy( fsk_path, input_path, PATH_LEN );
  1602.     memcpy( &(fsk_path[STRLEN(fsk_path) - 3]), "fsk", 3 );
  1603.     memcpy( hex_path, input_path, PATH_LEN );
  1604.     memcpy( &(hex_path[STRLEN(hex_path) - 3]), "hex", 3 );
  1605.     memcpy( cas_path, input_path, PATH_LEN );
  1606.     memcpy( &(cas_path[STRLEN(cas_path) - 3]), "cas", 3 );
  1607.  
  1608.     if( fsk )
  1609.         fsk_file = fopen( (char *)fsk_path, "w" );
  1610.     hex_file = fopen( (char *)hex_path, "w" );
  1611.     cas_file = fopen( (char *)cas_path, "wb" );
  1612.  
  1613. /*
  1614. **  Write the header to the cassette file.  The header makes it possible
  1615. **  to identify the file as a .cas file.  Also, the description is stored
  1616. **  in this header record.
  1617. */
  1618.     memcpy( cas_rec.cas_record_id, "FUJI", 4 );
  1619.     cas_rec.cas_len_lo = desc_len;
  1620.     cas_rec.cas_len_hi = desc_len / 256;
  1621.     cas_rec.cas_aux1 = 0x00;
  1622.     cas_rec.cas_aux2 = 0x00;
  1623.     if( desc_len )
  1624.         memcpy( cas_rec.cas_data, desc, desc_len );
  1625.     fwrite( &cas_rec, 1, cas_rec.cas_len_hi * 256 + cas_rec.cas_len_lo + 8, cas_file );
  1626.  
  1627. /*
  1628. **  Write out default baud rate to the cassette file.
  1629. */
  1630.     memcpy( cas_rec.cas_record_id, "baud", 4 );
  1631.     cas_rec.cas_len_lo = 0;
  1632.     cas_rec.cas_len_hi = 0;
  1633.     cas_rec.cas_aux1 = 600 % 256;
  1634.     cas_rec.cas_aux2 = 600 / 256;
  1635.     fwrite( &cas_rec, 1, 8, cas_file );
  1636.  
  1637.  
  1638.     if( fsk )
  1639.         fprintf( fsk_file, "%.*s\n", desc_len, desc );
  1640.     fprintf( hex_file, "%.*s\n", desc_len, desc );
  1641.     fsk_print_first = TRUE;
  1642.  
  1643. /*
  1644. **      Process the data portion of the .wav file.
  1645. */
  1646.     stat = wav2fsk();
  1647.  
  1648.     cleanup();
  1649.  
  1650.     fprintf(stderr, "\nDone processing.\n");
  1651.  
  1652.     return 0;
  1653. }
  1654.  
  1655. /*****************************************************************************
  1656. **  MODIFICATION HISTORY
  1657. **
  1658. **  DATE        BY   Description
  1659. **  ----------  ---  ---------------------------------------------------------
  1660. **  1996/11/30  ERS  Project start
  1661. **  1997/05/01  ERS  Release 01.00
  1662. **
  1663. *****************************************************************************/
  1664.